{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import OnePy as op\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Cleaner介绍"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from OnePy.sys_module.base_cleaner import CleanerBase\n",
    "\n",
    "class SMA(CleanerBase):\n",
    "    \"\"\"\n",
    "    编写自己的cleaner，只需自己创建一个CleanerBase的子类，然后覆盖calculate方法\n",
    "    默认提供data字典, key 为 ticker_frequency 的形式，比如 000001_D\n",
    "    self.data 内又是以open，high，low，close，volume为键值的字典, \n",
    "    每次事件循环只会保留固定rolling_window长度的数据\n",
    "    \"\"\"\n",
    "    \n",
    "    def calculate(self, ticker):\n",
    "        key = f'{ticker}_{self.frequency}'\n",
    "        close = self.data[key]['close']\n",
    "\n",
    "        return sum(close)/len(close)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "正在初始化OnePy\n",
      "=============== OnePy初始化成功！ ===============\n",
      "开始寻找OnePiece之旅~~~\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "+--------------------------------+\n",
      "|Fromdate           |  2018-03-01|\n",
      "|Todate             |  2018-10-01|\n",
      "|Initial_Value      |   $20000.00|\n",
      "|Final_Value        |   $19483.31|\n",
      "|Total_Return       |     -2.583%|\n",
      "|Max_Drawdown       |      2.959%|\n",
      "|Max_Duration       |    146 days|\n",
      "|Max_Drawdown_Date  |  2018-09-21|\n",
      "|Sharpe_Ratio       |       -2.04|\n",
      "+--------------------------------+\n"
     ]
    }
   ],
   "source": [
    "class SmaStrategy(op.StrategyBase): \n",
    "\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "        self.sma1 = SMA(rolling_window=3,   # 设置cleaner中data长度\n",
    "                        buffer_day= 40,     # 设置preload数据长度，过低会自动调整\n",
    "                        frequency='D'       # 设置需要用来计算的数据频率，默认为系统频率\n",
    "                       ).calculate\n",
    "        \n",
    "        self.sma2 = SMA(5, 40).calculate\n",
    "\n",
    "    def handle_bar(self):\n",
    "        for ticker in self.env.tickers:\n",
    "            if self.sma1(ticker) > self.sma2(ticker):\n",
    "\n",
    "                self.buy(100, ticker, takeprofit=15,\n",
    "                         stoploss=100)\n",
    "            else:\n",
    "                self.sell(100, ticker)\n",
    "\n",
    "\n",
    "TICKER_LIST = ['000001']\n",
    "INITIAL_CASH = 20000\n",
    "FREQUENCY = 'D'\n",
    "START, END = '2018-03-01', '2018-10-01'\n",
    "\n",
    "# 实例化策略，会自动添加到env.strategies中，key为类名\n",
    "SmaStrategy()\n",
    "\n",
    "# 用MongoDB数据库回测\n",
    "go = op.backtest.stock(TICKER_LIST, FREQUENCY, INITIAL_CASH, START, END)\n",
    "\n",
    "go.sunny()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Start!\n",
      "<<000001, H1>> has completed, Total: 482\n",
      "['000001'],H1 all set!!!!!\n",
      "<<000001, H1>> has been drop 482 duplicates!\n"
     ]
    }
   ],
   "source": [
    "from OnePy.builtin_module.mongodb_saver.tushare_saver import  multi_tushare_to_mongodb\n",
    "from OnePy.builtin_module.mongodb_saver.utils import MongoDBFunc\n",
    "\n",
    "# 保存H1数据\n",
    "FREQUENCY = [\"H1\"]  # 注意Tushre的H1数据只有从2018年开始的数据\n",
    "START = '2018-02-01'\n",
    "TICKER_LIST = ['000001']\n",
    "\n",
    "multi_tushare_to_mongodb(ticker_list=TICKER_LIST, \n",
    "                         period_list=FREQUENCY,\n",
    "                         fromdate=START)\n",
    "\n",
    "MongoDBFunc().drop_duplicates(TICKER_LIST, FREQUENCY, 'tushare')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**尝试用不同的frequency的cleaner回测, 变成每次用H1数据计算SMA信号**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "正在初始化OnePy\n",
      "=============== OnePy初始化成功！ ===============\n",
      "开始寻找OnePiece之旅~~~\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "+--------------------------------+\n",
      "|Fromdate           |  2018-04-01|\n",
      "|Todate             |  2018-10-01|\n",
      "|Initial_Value      |   $20000.00|\n",
      "|Final_Value        |   $19910.21|\n",
      "|Total_Return       |     -0.449%|\n",
      "|Max_Drawdown       |      1.396%|\n",
      "|Max_Duration       |     99 days|\n",
      "|Max_Drawdown_Date  |  2018-08-20|\n",
      "|Sharpe_Ratio       |       -0.83|\n",
      "+--------------------------------+\n"
     ]
    }
   ],
   "source": [
    "class SmaStrategy(op.StrategyBase):\n",
    "\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "        self.sma1 = SMA(rolling_window=3,   \n",
    "                        buffer_day= 10,     \n",
    "                        frequency='H1'       \n",
    "                       ).calculate\n",
    "        \n",
    "        self.sma2 = SMA(5, 10,'H1').calculate\n",
    "\n",
    "    def handle_bar(self):\n",
    "        for ticker in self.env.tickers:\n",
    "            if self.sma1(ticker) > self.sma2(ticker):\n",
    "\n",
    "                self.buy(100, ticker, takeprofit=15,\n",
    "                         stoploss=100)\n",
    "            else:\n",
    "                self.sell(100, ticker)\n",
    "\n",
    "\n",
    "TICKER_LIST = ['000001']\n",
    "INITIAL_CASH = 20000\n",
    "FREQUENCY = 'D'\n",
    "START, END = '2018-04-01', '2018-10-01'\n",
    "\n",
    "# 实例化策略，会自动添加到env.strategies中\n",
    "SmaStrategy()\n",
    "\n",
    "# 用MongoDB数据库回测\n",
    "go = op.backtest.stock(TICKER_LIST, FREQUENCY, INITIAL_CASH, START, END)\n",
    "\n",
    "go.sunny(show_process=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+--------------------+\n",
      "|readers_1  |  000001|\n",
      "+--------------------+\n",
      "+--------------------+\n",
      "|cleaners_1  |  SMA_1|\n",
      "|cleaners_2  |  SMA_2|\n",
      "+--------------------+\n",
      "+--------------------------+\n",
      "|strategy_1  |  SmaStrategy|\n",
      "+--------------------------+\n",
      "+-------------------------+\n",
      "|brokers_1  |  StockBroker|\n",
      "+-------------------------+\n",
      "+-----------------------------------------------+\n",
      "|risk_managers_1  |  StockLimitFilterRiskManager|\n",
      "+-----------------------------------------------+\n",
      "+-----------------------------+\n",
      "|recorders_1  |  StockRecorder|\n",
      "+-----------------------------+\n"
     ]
    }
   ],
   "source": [
    "go.output.show_setting()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Strategy介绍"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "class SmaStrategy(op.StrategyBase):\n",
    "\n",
    "    def __init__(self):\n",
    "        super().__init__() # 需要继承父类构造函数\n",
    "        \n",
    "    def handle_bar(self):\n",
    "        pass\n",
    "    \n",
    "##         调取账户信息\n",
    "        # go.env.recorder.holding_pnl.latest(ticker='000001', long_or_short='long')\n",
    "        # go.env.recorder.realized_pnl\n",
    "        # go.env.recorder.commission\n",
    "        # go.env.recorder.market_value\n",
    "        # go.env.recorder.margin\n",
    "        # go.env.recorder.position\n",
    "        # go.env.recorder.avg_price\n",
    "        # go.env.recorder.cash\n",
    "        # go.env.recorder.frozen_cash\n",
    "        # go.env.recorder.balance        \n",
    "        \n",
    "##         Function\n",
    "#         self.cur_price\n",
    "#         self.buy\n",
    "#         self.sell\n",
    "#         self.short\n",
    "#         self.cover\n",
    "#         self.cancel_pending\n",
    "#         self.cancel_tst\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
